
import { sys } from 'cc'
import { Md5 } from './Md5'

const serviceHost = 'https://service.cxgame.net/wxgame/'
const signKey = '2908953aecf9896815902cb2028da8ae'
const saveProfileUrl = 'set-profile'
const getProfileUrl = 'get-profile'
const submitWorldScoreUrl = 'submit-score'
const getWorldRankDataUrl = 'get-rank'

export class WXGameService {
	static postData<T>(url: string = '', params: Record<string, any> = {}, headers: Record<string, string> = {}): Promise<{
		code: number,
		msg: string
		data: T
	}> {
		return new Promise((resolve, reject) => {
			const xhr = new XMLHttpRequest()
			xhr.open('POST', url, true)
			if (sys.isNative) {
				xhr.setRequestHeader('Accept-Encoding', 'gzip,deflate')
			}
			xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

			for (let headersKey in headers) {
				xhr.setRequestHeader(headersKey, headers[headersKey]);
			}

			// note: In Internet Explorer, the timeout property may be set only after calling the open()
			// method and before calling the send() method.
			xhr.timeout = 30000 // 30 seconds for timeout

			var paramStr = ''
			for (var item in params) {
				paramStr += item + '=' + encodeURIComponent(params[item]) + '&'
			}
			xhr.send(paramStr)
			xhr.onreadystatechange = () => {
				if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 500) {
					const responseText = xhr.responseText
					let response: {
						code: number,
						msg: string
						data: T
					};
					// 兼容哔哩哔哩小游戏
					if (typeof responseText === "object") {
						response = responseText;
					}
					else {
						response = JSON.parse(responseText);
					}

					if (response.code !== 200) {
						reject(response);
					}
					else {
						resolve(response)
					}
				}
				else if (xhr.readyState === 4 && xhr.status === 503) {
					reject({
						msg: "limit request"
					});
				}
			}
		})
	}

	static async wrapPostDataSuccess(url: string = '', params: Record<string, any> = {}, headers: Record<string, string> = {}): Promise<boolean> {
		return new Promise<boolean>(resolve => {
			this.postData(url, params, headers)
				.then(() => resolve(true))
				.catch((e) => {
					console.error("post fail", url, e);
					resolve(false);
				})
		});
	}

	static parseQueryString(obj) {
		let str = ''
		for (let key in obj) {
			str += key + '=' + obj[key] + '&'
		}
		return str
	}

	static generatePar(par) {
		const sdic = Object.keys(par).sort()
		const content_list = []
		for (var ki in sdic) {
			content_list.push(sdic[ki] + '=' + par[sdic[ki]])
		}
		let content = content_list.join('&')
		content += signKey
		par.sign = Md5.hashStr(content)
	}

	static getProfile<TProfile>(appId: string, uid: string): Promise<{
		msg: string
		code: number,
		data: {
			profile: TProfile
		}
	}> {
		const par = {
			app_id: appId,
			uid: uid,
		}
		this.generatePar(par)
		return this.postData(serviceHost + getProfileUrl, par, {
			"app-id-uid": `get-profile-${appId}-${uid}`
		})
	}

	static async saveProfile(appId: string, uid: string, profile: string): Promise<{
		code: number
		msg: string,
		data: {
			profile: string
		}
	}> {
		const par = {
			app_id: appId,
			uid: uid,
			profile: profile,
		}
		this.generatePar(par)
		return this.postData(serviceHost + saveProfileUrl, par, {
			"app-id-uid": `set-profile-${appId}-${uid}`
		});
	}

	
	/**
	 * 提交世界排名分数
	 * @param app_id 应用ID
	 * @param uid 用户ID
	 * @param rank_key 排名键
	 * @param score 分数
	 * @param info 附加信息
	 * @returns 是否提交成功
	 */
	static submitWorldScore(app_id, uid, rank_key, score, info=null): Promise<boolean> {
		// 打印日志，记录提交的分数信息
		console.log('submitWorldScore ' + app_id + ' ' + uid + ' ' + rank_key + ' ' + score);
		// 打印附加信息
		console.log(info);
		// 如果应用ID为空，则返回
		if (!app_id) {
			return;
		}
		// 如果用户ID为空，则返回
		if (!uid) {
			return;
		}
		// 如果排名键为空，则返回
		if (!rank_key) {
			return;
		}
		// 创建一个对象，包含提交的分数信息
		var par = {
			app_id: app_id,
			uid: uid,
			key: rank_key,
			score: score,
			info: info,
		};
		// 生成签名
		this.generatePar(par);
		// 提交分数到服务器，并返回结果
		return this.wrapPostDataSuccess(serviceHost + submitWorldScoreUrl, par, {
			// "app-id-uid": `submit-ws-${app_id}-${uid}`
			"app-id-uid": `submit-ws-${app_id}-${uid}-${rank_key}`
		});
	}

	static getWorldRankData(app_id, uid, rank_key, group, count) {
		if (!group) {
			group = ''
		}
		var par = {
			app_id: app_id,
			uid: uid,
			key: rank_key,
			group: group,
			count: count,
		}
		this.generatePar(par)
		return this.postData(serviceHost + getWorldRankDataUrl, par, {
			// 这个接口不限制
			// "app-id-uid": `get-rank-${app_id}-${uid}`
		})
	}
}
